import json
import time
import logging
import datetime
import pandas as pd

import QUANTAXIS as QA
from QUANTAXIS.QAARP import QA_Risk
from QUANTAXIS.QAStrategy.classic_strategy.grid_strategy import GridTrade
from QUANTAXIS.QASU.save_account import delete_account


def gen_params():
    pos_2 = [[1.0, 0.8, 0.5, 0.2, 0.0],
             [0.9, 0.7, 0.5, 0.3, 0.1],
             [0.8, 0.7, 0.5, 0.3, 0.2],
             [0.7, 0.6, 0.5, 0.4, 0.3]]
    pos_3 = [[1.0, 0.9, 0.7, 0.5, 0.3, 0.1, 0.0],
             [0.9, 0.8, 0.7, 0.5, 0.3, 0.2, 0.1],
             [0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2]]
    dis_2 = [[-3, -2, 2, 3],
             [-2, -1, 1, 2]]
    dis_3 = [[-3, -2, -1, 1, 2, 3]]
    errs = ['std', 'atr']
    for n in [30, 60, 90, 120, 150, 180, 240, 300]:
        for dead in [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6]:
            for i in range(2, 4):
                if i is 2:
                    for pos in pos_2:
                        for dis in dis_2:
                            for err in errs:
                                yield n, dead, pos, dis, err
                else:
                    for pos in pos_3:
                        for dis in dis_3:
                            for err in errs:
                                yield n, dead, pos, dis, err


def main_muti():
    # account
    username = 'admin'
    password = 'admin'

    # strategy
    print('start execute strategy')
    today = datetime.date.today()
    last_year = datetime.date.today() + datetime.timedelta(days=-365)

    start = last_year.strftime('%Y-%m-%d')
    end = today.strftime('%Y-%m-%d')
    # start = '2018-03-01'
    # end = '2020-06-30'
    weight_pos = [1.0, 0.8, 0.5, 0.2, 0.0]
    # weight_pos = [0.9, 0.7, 0.5, 0.3, 0.1]
    weight_pos = [1.0, 0.9, 0.7, 0.5, 0.3, 0.1, 0.0]
    weight_pos = [0.9, 0.8, 0.7, 0.5, 0.3, 0.2, 0.1]
    weight_distance = [-3, -2, 2, 3]
    # weight_distance = [-2, -1, 1, 2]
    weight_distance = [-3, -2, -1, 1, 2, 3]

    t = datetime.datetime.now()
    index = 0
    df = pd.DataFrame()
    for n, dead, pos, dis, err in gen_params():
        # if not (n==60 and dead==0 and pos== [1.0, 0.8, 0.5, 0.2, 0.0] and dis==[-2, -1, 1, 2] and err=='atr'):
        #     continue
        strategy = GridTrade(code='510300', market=QA.MARKET_TYPE.INDEX_CN, start=start, end=end,
                             frequence=QA.FREQUENCE.DAY, strategy_id=username, init_cash=1e5,
                             deadband=dead, dynamic=False, N=n, err=err,
                             weight_pos=pos, weight_distance=dis)
        strategy.run_backtest()
        # strategy.plot_grid()
        if strategy.trade_start_time is None:  # 防止评估没有交易记录的账户
            continue
        risk = QA_Risk(strategy.acc)
        # print(risk.risk_message)
        s = pd.Series(risk.risk_message)
        s['start'] = strategy.trade_start_time
        s['end'] = end
        s['err'] = err
        s['N'] = n
        s['deadband'] = dead
        s['pos'] = pos
        s['dis'] = dis
        df = df.append(s.to_frame().T)
        # print(df)
        # risk.plot_assets_curve().show()
        df.to_csv('bt_result.csv')
        index += 1
        print(index, n, dead, pos, dis, err, 'return:', s['annualize_return'], 'time:', datetime.datetime.now() - t)

    # strategy = GridTrade(username='grid_backtest_index', password='123456', code='510300',
    #                              market=QA.MARKET_TYPE.INDEX_CN, start=start, end=end,
    #                        frequence=QA.FREQUENCE.DAY, strategy_id=username, init_cash=1e5,
    #                        deadband=0.5, dynamic=True, N=60, err='std',
    #                      weight_pos=weight_pos, weight_distance=weight_distance)
    # strategy.run_backtest()
    # strategy.plot_grid()
    # risk = QA_Risk(strategy.acc)
    # # print(risk.risk_message)
    # # s = pd.Series(risk.risk_message)
    # # s['start'] = start
    # # print(s)
    # df = pd.DataFrame.from_dict(risk.risk_message, orient='index', columns=['values']).T
    # df.to_csv('bt_result.csv')
    # risk.plot_assets_curve().show()


def main():
    # account
    username = 'backtest'
    password = 'admin'

    # strategy
    print('start execute strategy')
    today = datetime.date.today()
    last_year = datetime.date.today() + datetime.timedelta(days=-365)

    start = last_year.strftime('%Y-%m-%d')
    end = today.strftime('%Y-%m-%d')
    # start = '2018-01-01'
    # end = '2022-01-13'
    # weight_pos = [1.0, 0.8, 0.5, 0.2, 0.0]
    weight_pos = [0.9, 0.7, 0.5, 0.3, 0.1]
    # weight_pos = [1.0, 0.9, 0.7, 0.5, 0.3, 0.1, 0.0]
    # weight_pos = [0.9, 0.8, 0.7, 0.5, 0.3, 0.2, 0.1]
    # weight_pos = [1.0, 0.9, 0.7, 0.5, 0.3, 0.1, 0.0]
    # weight_distance = [-3, -2, -1, 2, 4, 6]
    weight_distance = [-3, -2, -1, 2, 4, 6]
    # weight_distance = [-2, -1, 1, 2]
    # weight_distance = [-3, -2, -1, 1, 2, 3]

    strategy = GridTrade(code='510300', market=QA.MARKET_TYPE.INDEX_CN, start=start, end=end,
                           frequence=QA.FREQUENCE.DAY, strategy_id=username, init_cash=1e5,
                           deadband=0.1, dynamic=False, N=30, err='atr', atr_ratio=1,
                         weight_pos=weight_pos, weight_distance=weight_distance)
    strategy.run_backtest()
    strategy.plot_grid()
    risk = QA_Risk(strategy.acc)
    # print(risk.risk_message)
    # s = pd.Series(risk.risk_message)
    # s['start'] = start
    # print(s)
    df = pd.DataFrame.from_dict(risk.risk_message, orient='index', columns=['values']).T
    print(df)
    # df.to_csv('bt_result.csv')
    risk.plot_assets_curve()
    # 回测结束后，删除账户信息，保证下次回测不受之前账户的影响
    delete_account(account=username)

if __name__ == "__main__":
    # main_muti()
    main()